package init.luoyu.easymonitor.server.item.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.collect.Lists;
import init.luoyu.easymonitor.base.model.ServiceResult;
import init.luoyu.easymonitor.base.service.impl.BaseServiceImpl;
import init.luoyu.easymonitor.base.utils.CommonUtil;
import init.luoyu.easymonitor.base.utils.LocalDateUtil;
import init.luoyu.easymonitor.elastic.ElasticService;
import init.luoyu.easymonitor.server.device.business.service.IDeviceService;
import init.luoyu.easymonitor.server.device.repository.model.CoreDevice;
import init.luoyu.easymonitor.server.item.business.model.base.CreateCoreMonitorItem;
import init.luoyu.easymonitor.server.item.business.model.base.UpdateCoreMonitorItem;
import init.luoyu.easymonitor.server.item.business.model.dto.MonitorItemDataDTO;
import init.luoyu.easymonitor.server.item.business.service.IInterDeviceMonitorItemService;
import init.luoyu.easymonitor.server.item.business.service.IMonitorItemService;
import init.luoyu.easymonitor.server.item.repository.mapper.CoreMonitorItemMapper;
import init.luoyu.easymonitor.server.item.repository.model.CoreMonitorItem;
import init.luoyu.easymonitor.server.item.repository.model.DeviceMonitorItem;
import init.luoyu.easymonitor.zabbix.MonitorData;
import init.luoyu.easymonitor.zabbix.ZabbixConstant;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author LuoYu
 * 2021/5/4
 **/
@Service
@Slf4j
public class MonitorItemServiceImpl extends BaseServiceImpl<CoreMonitorItem, CoreMonitorItemMapper, CreateCoreMonitorItem, UpdateCoreMonitorItem> implements IMonitorItemService {
    public MonitorItemServiceImpl(CoreMonitorItemMapper mapper, IService<CoreMonitorItem> service) {
        super(mapper, service, CoreMonitorItem.class,"监控项");
    }

    @Resource
    private IDeviceService deviceService;

    @Resource
    private IInterDeviceMonitorItemService iInterDeviceMonitorItemService;

    @Resource
    private ElasticService<MonitorData> elasticService;


    @Override
    public  ServiceResult<List<MonitorItemDataDTO>> getMonitorDataByDeviceId(Long deviceId) {
        log.info("获取设备的监控数据 ----> 设备id：{}",deviceId);
        CoreDevice device = deviceService.getById(deviceId, "id");
        if(device == null) {
            log.error("设备不存在 ----> 设备id:{}",deviceId);
            return ServiceResult.error("设备不存在");
        }
        QueryWrapper<DeviceMonitorItem> deviceItemQuery = new QueryWrapper<>();
        deviceItemQuery.select("id","monitorItemId","createTime").eq("deviceId",deviceId);
        List<DeviceMonitorItem> items = iInterDeviceMonitorItemService.getMapper().selectList(deviceItemQuery);
        if(CommonUtil.isEmptyCollection(items)) {
            log.warn("该设备下没有监控项 ----> 设备id:{}",deviceId);
            return ServiceResult.success(Lists.newArrayList());
        }
        List<Long> ids = items.stream().map(DeviceMonitorItem::getMonitorItemId).collect(Collectors.toList());
        QueryWrapper<CoreMonitorItem> itemQuery = new QueryWrapper<>();
        itemQuery.select("id","itemName","bio").in("id",ids);
        List<CoreMonitorItem> monitorItemList = this.getMapper().selectList(itemQuery);
        Map<Long, CoreMonitorItem> itemMap = monitorItemList.stream().collect(Collectors.toMap(CoreMonitorItem::getId, Function.identity()));
        Map<Long, DeviceMonitorItem> monitorItemMap = items.stream().collect(Collectors.toMap(DeviceMonitorItem::getMonitorItemId, Function.identity()));
        List<MonitorItemDataDTO> dataDTOS = Lists.newArrayList();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.termQuery("deviceId", deviceId));
        boolQueryBuilder.filter(QueryBuilders.termsQuery("monitorItemId",ids));
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.from(0);
        sourceBuilder.sort("clock", SortOrder.DESC);
        sourceBuilder.size(ids.size());
        try {
            List<MonitorData> monitorData = elasticService.queryByBuilder(ZabbixConstant.ELASTIC_INDEX_NAME, sourceBuilder,MonitorData.class);
            if(!CommonUtil.isEmptyCollection(monitorData)) {
                monitorData.forEach(v-> {
                    MonitorItemDataDTO dataDTO = new MonitorItemDataDTO();
                    dataDTO.setMonitorItemId(v.getMonitorItemId());
                    dataDTO.setMonitorData(v.getValue());
                    dataDTO.setDeviceId(v.getDeviceId());
                    CoreMonitorItem item = itemMap.get(v.getMonitorItemId());
                    dataDTO.setItemBio(item.getBio());
                    dataDTO.setItemName(item.getItemName());
                    DeviceMonitorItem monitorItem = monitorItemMap.get(v.getMonitorItemId());
                    dataDTO.setCreateTime(monitorItem.getCreateTime());
                    dataDTO.setLastCheckTime(LocalDateUtil.timestampToLocalDateTime(v.getClock()));
                    dataDTOS.add(dataDTO);
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("查询监控数据时发生错误 ----> Error:{}",e.getMessage());
            return ServiceResult.error(e.getMessage());
        }
        return ServiceResult.success(dataDTOS);
    }
}
